package com.l024.loanthief.service;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.text.TextUtils;
import android.util.SparseArray;

import androidx.annotation.Nullable;

import com.alibaba.fastjson.JSON;
import com.l024.loanthief.constant.APPConstant;
import com.l024.loanthief.entity.ChatMessageEntity;
import com.l024.loanthief.entity.DeviceEntity;
import com.l024.loanthief.eventbus.ChatMessageEvent;
import com.l024.loanthief.utils.DeviceUtil;
import com.l024.loanthief.utils.Logutils;
import com.l024.loanthief.utils.ScanDeviceTool;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import io.reactivex.rxjava3.disposables.Disposable;

/**
 * @author wu_ming_zhi_bei
 * @date 2021/1/19 9:27
 * @Notes 扫描服务
 */
public class ScanService extends Service {
    private Disposable subscribe;

    private Runtime mRun = Runtime.getRuntime();// 获取当前运行环境，来执行ping，相当于windows的cmd
    private Process mProcess = null;// 进程
    private ThreadPoolExecutor mExecutor;
    /** 核心池大小 **/
    private static final int CORE_POOL_SIZE = 1;
    /** 线程池最大线程数 **/
    private static final int MAX_IMUM_POOL_SIZE = 255;
    private SparseArray<Runnable> runnableSparseArray = new SparseArray<>();
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        EventBus.getDefault().register(this);
    }

    @Subscribe(threadMode = ThreadMode.POSTING )
    public void sendMsg(ChatMessageEvent event) {
        if (event != null) {
            switch (event.getCode()) {
                case APPConstant.SCAN_LIST: {
                    scan();
                    break;
                }
            }
        }
    }

    /**
     RejectedExecutionHandler的四种拒绝策略
     *
     * hreadPoolExecutor.AbortPolicy:
     * 当线程池中的数量等于最大线程数时抛出java.util.concurrent.RejectedExecutionException异常.
     * 涉及到该异常的任务也不会被执行.
     *
     * ThreadPoolExecutor.CallerRunsPolicy():
     * 当线程池中的数量等于最大线程数时,重试添加当前的任务;它会自动重复调用execute()方法
     *
     * ThreadPoolExecutor.DiscardOldestPolicy():
     * 当线程池中的数量等于最大线程数时,抛弃线程池中工作队列头部的任务(即等待时间最久Oldest的任务),并执行新传入的任务
     *
     * ThreadPoolExecutor.DiscardPolicy():
     * 当线程池中的数量等于最大线程数时,丢弃不能执行的新加任务
     * @param intent
     * @param flags
     * @param startId
     * @return
     */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        mExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_IMUM_POOL_SIZE,
                2000, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(
                CORE_POOL_SIZE), new ThreadPoolExecutor.DiscardOldestPolicy());
        mExecutor.allowCoreThreadTimeOut(true);
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
        if(subscribe!=null){
            subscribe.dispose();
        }
        if(mExecutor!=null){
            mExecutor.shutdownNow();
        }
        Logutils.i("服务被关闭了");
    }

    //扫描局域网数据
    private void scan(){
        if(runnableSparseArray!=null&&runnableSparseArray.size()>0){
            for(int i=0;i<runnableSparseArray.size();i++){
                if(runnableSparseArray.get(i)!=null){
                    mExecutor.remove(runnableSparseArray.get(i));
                }
            }
        }
        //清空列表
        EventBus.getDefault().postSticky(new ChatMessageEvent(APPConstant.DELECT_DEVICT_LIST,"",""));
        //获取本地ip
        String locAddress = new ScanDeviceTool().getLocAddress();
        if (TextUtils.isEmpty(locAddress)) {
           Logutils.e( "扫描失败，请检查wifi网络");
            return;
        }
        //获取本地ip前缀
        String locAddrIndex = new ScanDeviceTool().getLocAddrIndex(locAddress);
        //
        for (int i = 1; i < 255; i++){
            final int lastAddress = i;// 存放ip最后一位地址 1-255
            Runnable run = new Runnable() {
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    String currentIp = locAddrIndex + lastAddress;
                    String ping = "ping -c 1 -w 3 " + currentIp;
                    if (locAddress.equals(currentIp)) // 如果与本机IP地址相同,跳过
                        return;
                    try {
                        mProcess = mRun.exec(ping);
                        int result = mProcess.waitFor();
                        if (result == 0) {
                           Logutils.e("扫描成功,Ip地址为：" + currentIp);
                           //创建socket连接
                            createSocket(currentIp);
                        } else {
                            // 扫描失败
                            //Log.d(TAG, "扫描失败");
                        }
                    } catch (Exception e) {
                        Logutils.e("扫描异常" + e.getMessage());
                    } finally {
                        if (mProcess != null){
                            mProcess.destroy();
                        }
                    }
                }
            };
            runnableSparseArray.append(i,run);
            mExecutor.execute(run);
        }

        //销毁线程池
        //mExecutor.shutdownNow();
    }

    /**
     * 创建socket链接
     */
    private void createSocket(String ip){
        Logutils.e("链接ip"+ip);
        try {
            Socket client = new Socket(ip, APPConstant.PORT);
            client.setKeepAlive(true);
            //获取Socket的输出流，用来发送数据到服务端
            PrintStream out = new PrintStream(client.getOutputStream());
            ChatMessageEntity message = new ChatMessageEntity();
            message.setType(APPConstant.CONNECT_CODE);
            message.setMsg(JSON.toJSONString(new DeviceUtil().getDeviceInfo()));
            out.println(JSON.toJSONString(message));
            Logutils.i(ip+"发送信息到服务器");
            InputStream inputStream = client.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String s = "";
            //收到服务器发送的消息设备信息然后在关闭链接
            boolean isClose = false;
            while (!isClose) {
               if( (s = bufferedReader.readLine()) != null){
                   Logutils.i("收到设备信息:"+s);
                   if(!TextUtils.isEmpty(s)){
                       DeviceEntity d = JSON.parseObject(s, DeviceEntity.class);
                       Logutils.e(d.toString());
                       EventBus.getDefault().postSticky(new ChatMessageEvent(APPConstant.CONNECT_CODE,"",d));
                   }
                   isClose = true;
               }
            }
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
        } catch (IOException e) {
            Logutils.e("此ip连接失败"+ip);
        }
    }
}
